﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Sealight.API.Framework;
using Sealight.Core.Domain;
using Sealight.Data;
using Sealight.API.Ioc;
using Sealight.Core.DataAdapter;

namespace Sealight.CoreAPI
{
    public class OrdersService : IOrdersService
    {
        public order AddOrder(order item)
        {
            if (item == null)
                throw new ArgumentNullException("item data is Null.");
            //persists
            #region start_unit_of_work
            IUnitOfWork uow = null;
            if (!UnitOfWork.IsStarted)
                uow = UnitOfWork.Start();
            else uow = UnitOfWork.Current;
            #endregion
            bool commitTrans = false;
            if (!uow.IsInActiveTransaction)
            {
                //if not in active transaction
                //then begin transaction and commit it later
                uow.BeginTransaction(); //start transaction
                commitTrans = true;
            }
            try
            {
                IOrderDataRepository repo = IocContainer.Container().Resolve<IOrderDataRepository>();
                IRepository<PaymentMethodEntity> repoPT = IocContainer.Container().Resolve<IRepository<PaymentMethodEntity>>();
                IUserRepository repoU = IocContainer.Container().Resolve<IUserRepository>();

                OrderEntity data = repo.GetById(item.id);
                if (data == null)
                    data = new OrderEntity();

                data.Name = item.name;
                data.OrderStatus = item.order_status;
                data.PaymentStatus = item.payment_status;
                data.OrderTotal = item.order_total;
                data.OrderDiscount = item.order_discount;
                data.CreatedDate = item.created_date;
                data.ModifiedDate = item.modified_date;

                if (item.user != null)
                    data.User = repoU.GetById(item.user.id);
                if (item.payment_method != null)
                    data.PaymentMethod = repoPT.GetById(item.payment_method.id);

                repo.SaveOrUpdate(data);
                if (commitTrans)
                    uow.TransactionalFlush();
                item = data.ToDataAdapter();
            }
            catch (Exception ex)
            {
                throw new Exception("Error saving Order data. ErrMsg: " + ex.Message, ex);
            }
            return item;
        }
        public order_product_variant AddOrderDetail(order_product_variant item)
        {
            if (item == null)
                throw new ArgumentNullException("item data is Null.");
            //persists
            #region start_unit_of_work
            IUnitOfWork uow = null;
            if (!UnitOfWork.IsStarted)
                uow = UnitOfWork.Start();
            else uow = UnitOfWork.Current;
            #endregion
            bool commitTrans = false;
            if (!uow.IsInActiveTransaction)
            {
                //if not in active transaction
                //then begin transaction and commit it later
                uow.BeginTransaction(); //start transaction
                commitTrans = true;
            }
            try
            {
                IOrderDataRepository repo = IocContainer.Container().Resolve<IOrderDataRepository>();
                IProductDataRepository repoP = IocContainer.Container().Resolve<IProductDataRepository>();

                OrderProductVariantEntity data = repo.GetOrderDetail(item.id);

                data.Quantity = item.quantity;
                data.Price = item.price;
                data.Attributes = item.attributes;
                data.AttributeDescription = item.attribute_description;
                data.DiscountAmount = item.discount_amount;

                data.Order = repo.GetById(item.order_id);

                if (item.product_variant != null)
                    data.ProductVariant = repoP.GetProductVariantByID(item.product_variant.id);


                repo.AddOrderDetail(data);
                if (commitTrans)
                    uow.TransactionalFlush();
                item = data.ToDataAdapter();
            }
            catch (Exception ex)
            {
                throw new Exception("Error saving Order detail data. ErrMsg: " + ex.Message, ex);
            }
            return item;
        }
        public order_note AddOrderNote(order_note item)
        {
            if (item == null)
                throw new ArgumentNullException("item data is Null.");
            //persists
            #region start_unit_of_work
            IUnitOfWork uow = null;
            if (!UnitOfWork.IsStarted)
                uow = UnitOfWork.Start();
            else uow = UnitOfWork.Current;
            #endregion
            bool commitTrans = false;
            if (!uow.IsInActiveTransaction)
            {
                //if not in active transaction
                //then begin transaction and commit it later
                uow.BeginTransaction(); //start transaction
                commitTrans = true;
            }
            try
            {
                IOrderDataRepository repo = IocContainer.Container().Resolve<IOrderDataRepository>();

                OrderNoteEntity data = repo.GetOrderNote(item.id);

                data.DisplayToUser = item.display_to_user;
                data.Note = item.note;
                if(item.order!= null)
                data.Order = repo.GetById(item.order.id);

                repo.AddOrderNote(data);
                if (commitTrans)
                    uow.TransactionalFlush();
                item = data.ToDataAdapter();
            }
            catch (Exception ex) { throw new Exception("Error saving Order Note data. ErrMsg: " + ex.Message, ex); }
            return item;
        }
        public IList<order> GetOrders()
        {
            if (!UnitOfWork.IsStarted)
                UnitOfWork.Start();

            IOrderDataRepository repo = IocContainer.Container().Resolve<IOrderDataRepository>();

            IList<OrderEntity> data = repo.GetAll();
            IList<order> result = null;

            if (data != null)
                result = (from c in data orderby c.CreatedDate descending select c.ToDataAdapter()).ToList();

            return result;
        }
        public order GetOrder(Guid id)
        {
            if (!UnitOfWork.IsStarted)
                 UnitOfWork.Start();

            IOrderDataRepository repo = IocContainer.Container().Resolve<IOrderDataRepository>();
            order result = null;

            OrderEntity data = repo.GetById(id);

            if (data != null)
                result = data.ToDataAdapter();
            return result;
        }
        public IList<order_product_variant> GetOrderDetails(Guid order_id)
        {
            if (!UnitOfWork.IsStarted)
                 UnitOfWork.Start();
            IOrderDataRepository repo = IocContainer.Container().Resolve<IOrderDataRepository>();
            IList<OrderProductVariantEntity> data = repo.GetOrderDetails(order_id);
            IList<order_product_variant> result = null;

            if (data != null)
                result = (from c in data select c.ToDataAdapter()).ToList();

            return result;
        }
        public IList<order> SearchOrders(string keyword, DateTime? from, DateTime? to)
        {
            if (!UnitOfWork.IsStarted)
                UnitOfWork.Start();

            IOrderDataRepository repo = IocContainer.Container().Resolve<IOrderDataRepository>();

            IList<OrderEntity> data = repo.SearchOrders(keyword, from, to);
            IList<order> result = null;

            if (data != null)
                result = (from c in data orderby c.CreatedDate descending select c.ToDataAdapter()).ToList();

            return result;
        }
    }
}
